import { DataNode } from 'antd/es/tree';
import React from 'react';
import { StarredSvgComponent, StarSvgComponent } from '../../icons';
import { getMaterialConfig } from '../common/MetalIconMapping';

// 递归地提取节点中的文本内容
function extractTextFromNode(
  node: React.ReactNode | ((data: DataNode) => React.ReactNode),
  dataNode: DataNode,
): string {
  // 如果 node 是函数类型，执行它并获取返回值
  if (typeof node === 'function') {
    const result = node(dataNode); // 执行函数并获取返回的 ReactNode
    return extractTextFromNode(result, dataNode); // 递归地提取
  }

  // 如果是 ReactNode，继续递归提取文本
  let text = '';
  React.Children.forEach(node, (child) => {
    if (typeof child === 'string') {
      text += child; // 获取字符串类型的文本
    } else if (React.isValidElement(child) && child.props?.children) {
      text += extractTextFromNode(child.props.children, dataNode); // 递归处理子元素
    }
  });

  return text.trim();
}

export function filterTree(tree: DataNode[], searchValue: string): any[] {
  if (!searchValue) return tree;

  return tree
    .map((node) => {
      const nodeTitleText = extractTextFromNode(node.title, node); // 提取标题的文本内容

      if (nodeTitleText.toLowerCase().includes(searchValue.toLowerCase())) {
        return node;
      }

      if (node.children) {
        const filteredChildren = filterTree(node.children, searchValue);
        if (filteredChildren.length) {
          return { ...node, children: filteredChildren };
        }
      }

      return null;
    })
    .filter(Boolean) as DataNode[];
}

// 定义节点类型枚举
export enum MaterialNodeType {
  FavRoot = 'fav-root', // 收藏夹根节点
  StandardLibRoot = 'standard-lib-root', // 标准材料库根节点
  CustomMat = 'custom-mat', // 自定义材料
  CustomCat = 'custom-cat', //自定义材料种类
  CustomLib = 'custom-lib', // 自定义库
  FavMaterial = 'fav-material', // 收藏夹材料
  StandardMaterialCategory = 'standard-material-category', // 标准材料库类别
  StandardMaterial = 'standard-material', // 标准材料
  Undefined = 'un-defined', // 未定义
}
export const getNodeTypeMark = (
  node?: CmdMaterialSpace.TreeNode,
): MaterialNodeType => {
  if (!node) return MaterialNodeType.Undefined;
  switch (node?.iconKey) {
    case 'collection':
      return MaterialNodeType.FavRoot;
    case 'standard-material-library':
      return MaterialNodeType.StandardLibRoot;
    case 'custom-material-library':
      return MaterialNodeType.CustomLib;
    default:
      if (node.parentTypeMark === MaterialNodeType.FavRoot)
        return MaterialNodeType.FavMaterial;
      if (node.parentTypeMark === MaterialNodeType.StandardLibRoot)
        return MaterialNodeType.StandardMaterialCategory;
      if (node.parentTypeMark === MaterialNodeType.StandardMaterialCategory)
        return MaterialNodeType.StandardMaterial;
      if (node.parentTypeMark === MaterialNodeType.CustomLib)
        return MaterialNodeType.CustomCat;
      if (node.parentTypeMark === MaterialNodeType.CustomCat)
        return MaterialNodeType.CustomMat;
      return MaterialNodeType.Undefined;
  }
};

interface ConvertToTreeDataExtras {
  favMatToCollection: (materialId: string) => void;
  unFavMatToCollection: (materialId: string, name: string) => void;
  selectNode?: CmdMaterialSpace.TreeNode;
}

export function getTreeByFactory(
  nodes: CmdMaterialSpace.TreeNode[],
  extras: ConvertToTreeDataExtras,
  parentTypeMark = '',
  parentName = '',
): DataNode[] {
  const { favMatToCollection, unFavMatToCollection, selectNode } = extras;
  return nodes.map((node) => {
    const Icon = getMaterialConfig(node.iconKey).icon;
    const typeMark = getNodeTypeMark({ ...node, parentTypeMark });
    return {
      title: (
        <div className='flex items-center w-44'>
          {Icon && <Icon style={{ width: 16, height: 16, marginRight: 4 }} />}
          <div className='flex justify-between flex-1'>
            <div
              className='truncate w-28'
              title={node.name}
            >
              {node.name}
            </div>
            <div>
              {node.collectFlag && (
                <StarredSvgComponent
                  onClick={(ev) => {
                    ev.stopPropagation();
                    unFavMatToCollection(node.id, node.name);
                  }}
                />
              )}
              {selectNode?.id === node.id &&
                !node.collectFlag &&
                [
                  MaterialNodeType.CustomMat,
                  MaterialNodeType.StandardMaterial,
                ].includes(selectNode.typeMark as MaterialNodeType) && (
                  <StarSvgComponent
                    onClick={(ev) => {
                      ev.stopPropagation();
                      favMatToCollection(node.id);
                    }}
                  />
                )}
            </div>
          </div>
        </div>
      ),
      key: node.id,
      children:
        node.subList && node.subList.length > 0
          ? getTreeByFactory(node.subList, extras, typeMark, node.name)
          : undefined,
      iconKey: node.iconKey,
      typeMark,
      parentTypeMark,
      parentName: parentName ?? '',
      parentId: node.pid,
      id: node.id,
      name: node.name,
      collectFlag: node.collectFlag,
    };
  });
}
export function getMenuItems(
  type: MaterialNodeType,
  node: CmdMaterialSpace.TreeNode,
) {
  switch (type) {
    case MaterialNodeType.FavMaterial:
      return [
        { key: 'copy', label: '复制材料' },
        { key: 'unfav', label: '取消收藏' },
      ];
    case MaterialNodeType.StandardMaterial:
      if (node.collectFlag) {
        return [
          { key: 'copy', label: '复制材料' },
          { key: 'unfav', label: '取消收藏' },
        ];
      } else {
        return [
          { key: 'copy', label: '复制材料' },
          { key: 'fav', label: '添加至收藏夹' },
        ];
      }
    case MaterialNodeType.CustomLib:
      return [
        { key: 'rename', label: '重命名' },
        { key: 'new-cat', label: '新建类别' },
        { key: 'delete', label: '删除' },
      ];
    case MaterialNodeType.StandardMaterialCategory:
      return [];
    case MaterialNodeType.CustomCat:
      return [
        { key: 'rename', label: '重命名' },
        { key: 'new-mat', label: '新建材料' },
        { key: 'paste', label: '粘贴' },
        { key: 'delete', label: '删除' },
      ];
    case MaterialNodeType.CustomMat:
      if (node.collectFlag) {
        return [
          { key: 'unfav', label: '取消收藏' },
          { key: 'rename', label: '重命名' },
          { key: 'copy', label: '复制' },
          { key: 'delete', label: '删除' },
        ];
      } else {
        return [
          { key: 'fav', label: '添加至收藏夹' },
          { key: 'rename', label: '重命名' },
          { key: 'copy', label: '复制' },
          { key: 'delete', label: '删除' },
        ];
      }
    default:
      return [];
  }
}

export function isFieldsChanged<T extends string>(
  keys: T[],
  obj1: Partial<Record<T, any>>,
  obj2: Partial<Record<T, any>>,
): boolean {
  return keys.some((key) => {
    const v1 = obj1[key] ?? '';
    const v2 = obj2[key] ?? '';
    return v1 !== v2;
  });
}
